﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ZDT.Text
{
    public class StringMatch
    {
        /// <summary>
        /// 根据各个替换规则处理字符串
        /// </summary>
        /// <param name="source">要处理的字符串</param>
        /// <param name="startMark">开始字符串</param>
        /// <param name="endMark">结束字符串</param>
        /// <param name="profix">替换/前缀/后缀的字符串</param>
        /// <param name="replaceRule">操作类型</param>
        /// <param name="headTail">包含头尾</param>
        /// <returns>返回处理过后的字符串</returns>
        public static string Parse(string source, string startMark, string endMark, string profix, ReplaceRule replaceRule, DescPlace headTail)
        {
            int intLength = source.Length;
            int startIndex = source.IndexOf(startMark);
            int endIndex = 0;
            if (startIndex == -1)
            {
                endIndex = source.IndexOf(endMark);
            }
            else 
            {
                endIndex = source.IndexOf(endMark, startIndex + startMark.Length);
            }
            bool hasHead = (headTail & DescPlace.Head) == DescPlace.Head;
            bool hasTail = (headTail & DescPlace.Tail) == DescPlace.Tail;
            switch (replaceRule)
            {
                case ReplaceRule.Match://截取
                    if (endIndex <= startIndex || startIndex == -1)
                        return "";

                    if (hasHead && hasTail)//表示包含头尾,保证能找到尾
                    {
                        return source.Substring(startIndex, endIndex - startIndex + endMark.Length);

                    }

                    if (hasHead && !hasTail)//表示包含头，不包含尾
                    {
                        return source.Substring(startIndex, endIndex - startIndex);
                    }

                    if (!hasHead && hasTail)//表示不包含头，包含尾
                    {
                        return source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length + endMark.Length);
                    }

                    if (!hasHead && hasTail)//表示不包含头，也不包含尾
                    {
                        return source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length);
                    }
                    break;
                case ReplaceRule.ReplaceMatch://删除段
                    if (endIndex <= startIndex || startIndex == -1)
                        return source;

                    if (hasHead && hasTail)//表示包含头尾
                    {
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex + endMark.Length), "");
                    }

                    if (hasHead && !hasTail)//表示包含头，不包含尾
                    {
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex), "");
                    }

                    if (!hasHead && hasTail)//表示不包含头，包含尾
                    {
                        return source.Replace(source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length + endMark.Length), "");
                    }

                    if (!hasHead && !hasTail)//表示不包含头，也不包含尾
                    {
                        return source.Replace(source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length), "");
                    }
                    break;
                case ReplaceRule.ReplaceHeadMark://删除字符串
                    return source.Replace(startMark, "");
                    break;
                case ReplaceRule.ReplaceProfixHeadMark://字符串前缀
                    return source.Replace(startMark, profix + startMark);
                    break;
                case ReplaceRule.ReplaceProfixMatch://段落前缀
                    if (endIndex <= startIndex || startIndex == -1)
                        return source;
                    if (hasHead)
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex), profix + source.Substring(startIndex, endIndex - startIndex));

                    if (!hasHead)
                        return source.Replace(source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length), profix + source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length));
                    break;
                case ReplaceRule.ReplaceHeadMarkProfix://字符串后缀
                    return source.Replace(startMark, startMark + profix);
                    break;
                case ReplaceRule.ReplaceMatchProfix://段落后缀
                    if (endIndex <= startIndex || startIndex == -1)
                        return source;

                    if (hasTail)
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex + endMark.Length), source.Substring(startIndex, endIndex - startIndex + endMark.Length) + profix);

                    if (!hasTail)
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex), profix + source.Substring(startIndex, endIndex - startIndex) + profix);
                    break;
                case ReplaceRule.ReplaceHeadMarkToProfix://替换字符串
                    return source.Replace(startMark, profix);
                    break;
                case ReplaceRule.ReplaceMatchToProfix://替换段落
                    if (hasHead && hasTail)//表示包含头尾
                    {
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex + endMark.Length), profix);
                    }

                    if (hasHead && !hasTail)//表示包含头，不包含尾
                    {
                        return source.Replace(source.Substring(startIndex, endIndex - startIndex), profix);
                    }

                    if (!hasHead && hasTail)//表示不包含头，包含尾
                    {
                        return source.Replace(source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length + endMark.Length), profix);
                    }

                    if (!hasHead && !hasTail)//表示不包含头，也不包含尾
                    {
                        return source.Replace(source.Substring(startIndex + startMark.Length, endIndex - startIndex - startMark.Length), profix);
                    }
                    break;
            }
            return source;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="regex"></param>
        /// <param name="groupName"></param>
        /// <returns></returns>
        public static string Match(string source, Regex regex,string groupName="r")
        {
            string result = string.Empty;
            var m = regex.Match(source);
            if (m != null)
            {
                var group = m.Groups[groupName];
                if (group != null)
                {
                    result = group.Value;
                }
                else
                {
                    result = m.Value;
                }
            }
            return result;
        }
        private static Dictionary<string, Regex> _RegexCaches = new Dictionary<string, Regex>();
        private static Regex GetRegexCache(string pattern, bool hasCache)
        {
            Regex result = null;
            if (!hasCache || !_RegexCaches.ContainsKey(pattern))
            {
                result = new Regex(pattern);
                if (hasCache)
                {
                    _RegexCaches.Add(pattern, result);
                }
            }
            else
            {
                result = _RegexCaches[pattern];
            }
            return result;
        }
        private static string GetMatchValue(Match match, string groupName = "r")
        {
            string result = string.Empty;
            if (match != null)
            {
                var group = match.Groups[groupName];
                if (group != null)
                {
                    result = group.Value;
                }
                else
                {
                    result = match.Value;
                }
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="pattern"></param>
        /// <param name="hasCache"></param>
        /// <returns></returns>
        public static string Match(string source, string pattern, bool hasCache = true, string groupName = "r")
        {
            var regex = GetRegexCache(pattern, hasCache);
            return Match(source, regex, groupName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="patternSetting"></param>
        /// <returns></returns>
        public static List<PatternResult> Match(PatternSetting patternSetting)
        {
            List<PatternResult> result = new List<PatternResult>();
            var regex = GetRegexCache(patternSetting.Pattern, true);
            Match match = regex.Match(patternSetting.Source);
            bool hasChild = patternSetting.Childs.Count > 0;
            while (match != null)
            {
                var pr = new PatternResult();
                pr.Result = GetMatchValue(match, patternSetting.Name);
                if (hasChild)
                {
                    foreach (var item in patternSetting.Childs)
                    {
                        var pr2 = new PatternResult();
                        pr2.Result = Match(pr.Result, item.Value.Pattern, true, item.Value.Name);
                        pr.Childs.Add(item.Key, pr2);
                    }
                }
                result.Add(pr);
                match = match.NextMatch();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="patternSetting"></param>
        /// <param name="groupNames"></param>
        /// <returns></returns>
        public static List<Dictionary<string, string>> Match(PatternSetting patternSetting, List<string> groupNames)
        {
            List<Dictionary<string, string>> result = new List<Dictionary<string, string>>();
            var regex = GetRegexCache(patternSetting.Pattern, true);
            Match match = regex.Match(patternSetting.Source);
            bool hasChild = patternSetting.Childs.Count > 0;
            while (match != null)
            {
                var item = new Dictionary<string, string>();
                item.Add(patternSetting.Name, GetMatchValue(match, patternSetting.Name));
                foreach (var groupName in groupNames)
                {
                    item.Add(groupName, GetMatchValue(match, groupName));
                }
                result.Add(item);
            }
            return result;
        }
        #region 常理
        public static string HP = @"http";
        public static string HPS = @"http";
        public static string HPH = @"http://";
        public static string HPSH = @"https://";
        #endregion

        #region 特殊正则
        public static Regex RHttpRoot = new Regex(@"http[s]?\://[^/]+");
        public static Regex RHttpPath = new Regex(@"http[s]?\://[^?]+");
        public static Regex RText = new Regex(@"\><r>(.*?)\<");
        public static Regex RSingleQuotes = new Regex(@"[^']*");
        public static Regex RDougleQuotes = new Regex(@"[^""]*");
        public static Regex RBrackets = new Regex(@"\(<r>(.*?)\)");
        #endregion
    }
}
